﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Identity;
using WMSSystem.DYB.Dto.LocationManagement.Input;
using WMSSystem.DYB.Dto.LocationManagement.Output;
using WMSSystem.DYB.Dto.WarehouseManagement.Output;
using WMSSystem.DYB.Interface;
using WMSSystem.YSL.Interfance;
using static Microsoft.FSharp.Core.ByRefKinds;

namespace WMSSystem.DYB.Application
{
    public class LocationManageService : ApplicationService, IApplicationService, ILocationManagementService
    {
        private readonly IRepository<LocationManagement,Guid> _locationRepository;
        private readonly IRepository<WarehouseManagement,Guid> _warehouseRepository;
        private readonly IRepository<IdentityUser, Guid> _userrepository;
        private readonly ICodeRuleAppService _codeRuleAppService;
        public LocationManageService(IRepository<LocationManagement, Guid> locationRepository, IRepository<WarehouseManagement, Guid> warehouseRepository, IRepository<IdentityUser, Guid> userrepository, ICodeRuleAppService codeRuleAppService)
        {
            _locationRepository = locationRepository;
            _warehouseRepository = warehouseRepository;
            _userrepository = userrepository;
            _codeRuleAppService = codeRuleAppService;
        }
        /// <summary>
        /// 新建库位
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<ApiResponse<CreateLocationInput>> CreateLoaction(CreateLocationInput input)
        {
            using(TransactionScope scope = new TransactionScope())
            {
                try
                {
                    var model = ObjectMapper.Map<CreateLocationInput, LocationManagement>(input);
                    model.Num = 0;
                    model.Code = await _codeRuleAppService.GenerateCodeAsync("location");
                    model.CreatorId = new Guid("3a1b4d19-6f9c-7e5e-9f1f-ce1da55e4f1e");
                    model.LastModificationTime = DateTime.Now;
                    model.LastModifierId = new Guid("3a1b4d19-6f9c-7e5e-9f1f-ce1da55e4f1e");
                    
                    var warehouse = await _warehouseRepository.GetAsync(x => x.Id == input.WarehouseManagementId);
                    var num = warehouse.UseCapacity + model.Capacity;
                    
                    if(num > warehouse.Capacity)
                    {
                        throw new Exception("新建库位失败,仓库容量不足");
                    }
                    warehouse.Num += 1;
                    warehouse.UseCapacity += model.Capacity;
                    await _locationRepository.InsertAsync(model);
                    await _warehouseRepository.UpdateAsync(warehouse);
                    scope.Complete();
                    return new ApiResponse<CreateLocationInput>()
                    {
                        Code = ErrorCode.Success,
                        Message = "新建库位成功",
                        Data = input
                    };
                }
                catch (Exception ex)
                {
                    return new ApiResponse<CreateLocationInput>()
                    {
                        Code = ErrorCode.Error,
                        Message = ex.Message,
                        Data = input
                    };
                    throw;
                }
            }
            
        }
        /// <summary>
        /// 删除库位
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<Guid> DeleteLocation(Guid Id)
        {
            var location = await _locationRepository.GetAsync(Id);
            var warehouse = await _warehouseRepository.GetAsync(location.WarehouseManagementId);
            using (TransactionScope scope = new TransactionScope())
            {
                try
                {
                    await _locationRepository.DeleteAsync(location);
                    warehouse.Num -= 1;
                    warehouse.UseCapacity -= location.Capacity;
                    await _warehouseRepository.UpdateAsync(warehouse);
                    scope.Complete();
                    return location.Id;
                }
                catch (Exception ex)
                {
                    throw;
                }
            }
            
        }
        /// <summary>
        /// 根据Id查找库位详情
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<GetLoactionOutput> GetLoaction(Guid Id)
        {
            var location = await _locationRepository.GetAsync(Id);
            var users = await _userrepository.GetAsync(location.LocationSupervisorId);
            Expression<Func<IdentityUser, bool>> expression = x => x.Id == location.CreatorId;
            var userss = await _userrepository.GetAsync(expression);
            GetLoactionOutput output = ObjectMapper.Map<LocationManagement, GetLoactionOutput>(location);
            output.LocationSupervisorName = users.UserName;
            output.CreatorName = userss.UserName;
            output.LastModifierName = "admin";
            return output;
        }

        /// <summary>
        /// 根据仓库编号获取所有相关库位数据
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<List<GetLoactionListOutput>> GetLoactionList(GetLoactionListInput input)
        {
            var locationlist = await _locationRepository.GetQueryableAsync();
            var userlist = await _userrepository.GetQueryableAsync();
            locationlist = locationlist.Where(x => x.WarehouseManagementId == input.Id);
            var output = from a in locationlist
                         join c in userlist on a.LocationSupervisorId equals c.Id
                         select new GetLoactionListOutput
                         {
                             Capacity = a.Capacity,
                             Code = a.Code,
                             Id = a.Id,
                             LocationSupervisorName = c.UserName,
                             State = a.State,
                             Name = a.Name,
                             Remark = a.Remark,
                             LastModifierName = "admin",
                             LastModificationTime = a.LastModificationTime,
                         };
            return output.ToList();
        }
    }
}
